package com.gopay.webtest.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.time.StopWatch;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.xml.sax.InputSource;

import com.gopay.webtest.controller.base.BaseController;
import com.gopay.webtest.util.BaseSign;
import com.gopay.webtest.util.HttpClientUtil;
import com.gopay.webtest.vo.SC03Vo;
import com.gopay.webtest.vo.WeChatPayInfo;
import com.gopay.webtest.xml.XmlDao;

/**
 * 
 * @ClassName: WXGZHPayController
 * @Description: 微信公众号支付
 * @author dhj
 * @date 2016年10月11日 下午6:06:45
 */
@SuppressWarnings("all")
@Controller
public class WXGZHPayController extends BaseController {

    private static final String CHARSET_GBK = "1";

    @Resource(name = "paySignHandler")
    private BaseSign paySignHandler;
    
    private static Map<String, String> map = null;

    @Autowired
    public WXGZHPayController(@Qualifier(value = "xmlDao") XmlDao xmlDao) {
        try {
            map = xmlDao.readData4Map("wxgzh_pay", "payapply");
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 
     * @Description: 微信公众号支付提交
     * @return
     * @author dhj
     */
    @RequestMapping("/wxgzhPay")
    public ModelAndView pay() {
        ModelAndView mav = new ModelAndView();
        WeChatPayInfo payinfo = getDefaultInfoFromXML();
        mav.setViewName("gopay.webtest.wxgzh.index");
        mav.addObject("payInfo", payinfo);
        return mav;
    }

    /**
     * 
     * @Description: 获取初始化数据
     * @return
     * @author Adimn
     */
    private WeChatPayInfo getDefaultInfoFromXML() {
    	WeChatPayInfo payInfo = new WeChatPayInfo();

        payInfo.setMerchantID((String) map.get("merchantID"));
        payInfo.setBackgroundMerUrl((String) map.get("backgroundMerURL"));
        payInfo.setCurrencyType((String) map.get("currType"));
        payInfo.setTranDateTime(com.gopay.webtest.util.DateUtils.date2string(new Date(),
                com.gopay.webtest.util.DateUtils.DEFAULT_PATTERN));
        payInfo.setGopayServerTime(com.gopay.webtest.util.DateUtils.date2string(new Date(),
                com.gopay.webtest.util.DateUtils.DEFAULT_PATTERN));
        payInfo.setTranIP((String) map.get("tranIP"));
        payInfo.setVirCardNoIn((String) map.get("virCardNoIn"));
        payInfo.setSubOpenId(map.get("subOpenId"));
        return payInfo;
    }

    /**
     * 提交交易到国付宝网关
     * 
     * @param payInfo
     * @return
     */
    @RequestMapping("/wxgzhSubmit")
    public ModelAndView paySubmit(WeChatPayInfo payInfo,
    	HttpServletRequest request,HttpServletResponse response) {
    	String isWebtestRedirect = (String)request.getSession().getAttribute("isWebtestRedirect");
    	
        ModelAndView mav = new ModelAndView();
        String backgroundMerUrl = payInfo.getBackgroundMerUrl();
        if (backgroundMerUrl != null && !backgroundMerUrl.equals("")) {
            backgroundMerUrl = backgroundMerUrl + "?id=" + payInfo.getVerficationCode();
        }

        payInfo.setBackgroundMerUrl(backgroundMerUrl);

        StopWatch sw = new StopWatch();

        // 设置MD5加密字段
        try {
            sw.start();
            paySignHandler.sign(payInfo.getTranCode() + "_" + payInfo.getVersion(), "signType", "signValue", payInfo, request);
            sw.stop();
            logger.info("step1 time:" + sw.getTime());
            logger.info("webtest生成的加签值:" + payInfo.getSignValue());
        } catch (Exception e) {
            e.printStackTrace();
        }
        String signedValue = payInfo.getSignValue();
        if (null == signedValue) {
            // 加密操作失败,置返回码为身份认证md5加密失败
            payInfo.setRespCode("MR08");
            mav.setViewName("gopay.webtest.wxgzh.index");
        }else if(isWebtestRedirect==null||"true".equals(isWebtestRedirect)){
        	Map<String,String> url=(Map)request.getSession().getAttribute("gopay_webtest_URL");
        	String reqURL = url.get("dom")+url.get("wechatPay");
        	Map<String, String> params = null;
			try {
				params = PropertyUtils.describe(payInfo);
				params.remove("class");
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        	String encodeCharset = payInfo.getCharset().equals("1")?"GBK":"UTF-8";
        	String decodeCharset = payInfo.getCharset().equals("1")?"GBK":"UTF-8";
        	 logger.info("准备发送报文到gateway:");
        	 logger.info("请求地址:"+reqURL+"，字符集："+encodeCharset);
        	String respText = HttpClientUtil.sendPostRequest(reqURL, params, encodeCharset, decodeCharset);
        	 logger.info("接受到的gateway报文：" + respText);
        	SC03Vo vo = null;
        	if(isErrorXML(respText,encodeCharset,mav)){
        		mav.addObject("error", "true");
        		mav.setViewName("forward:/payConfirm.do");
        	}else{
        		mav.addObject("error", "false");
        		vo = redirectWebtest(respText,encodeCharset);
        		//mav.addObject("sc03", vo);
        		mav.setViewName("redirect:/payConfirm.do"+"?appId="+vo.getAppId()+"&timeStamp="+vo.getTimeStamp()
        		+"&signType="+vo.getSignType()+"&package1="+vo.getPackage1()+"&nonceStr="+vo.getNonceStr()+"&paySign="+vo.getPaySign());
        	}
        	//mav.setViewName("gopay.webtest.wxgzhPayConfirm");
        } else {
            if (!payInfo.getCharset().equals("2")) {
                mav.setViewName("gopay.webtest.wxgzhFormSubmit_gbk");
            } else {
                mav.setViewName("gopay.webtest.wxgzhFormSubmit");
            }
            mav.addObject("payInfo", payInfo);
        }
        return mav;
    }
    
    /**
     * 调起微信支付模块，以便于完成微信支付流程
     * @Description:
     * @return 
     * @author dhj
     */
    @RequestMapping("/payConfirm")
    public ModelAndView payConfirm(SC03Vo sc03) {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("gopay.webtest.wxgzhPayConfirm");
        mav.addObject("sc03", sc03);
        return mav;
    }
    
    @SuppressWarnings("unchecked")
	private boolean isErrorXML(String xmlStr,String encodeCharset,ModelAndView vo){
    	boolean error = false;
    	Map<String,String> data = new HashMap<String,String>();
    	try{
    	SAXReader reader = new SAXReader(false);
    	InputSource source = new InputSource(new ByteArrayInputStream(xmlStr.getBytes(encodeCharset)));
    	source.setEncoding(encodeCharset);
    	Document doc = reader.read(source);
    	List<Element> els = doc.getRootElement().elements();
    	 for(Element el : els){
    		 if(("respCode".equals(el.getName())&&!"0000".equals(el.getTextTrim()))
    			||"errCode".equals(el.getName())){
    			 error = true;
    		 }
    		 data.put(el.getName(), el.getTextTrim());
    	  }
    	 vo.addObject("data", data);
    	}catch(DocumentException | UnsupportedEncodingException e){
    		e.printStackTrace();
    	}
    	return error;
    }
    @SuppressWarnings("unchecked")
	private SC03Vo redirectWebtest(String xmlStr,String encodeCharset){
    	SC03Vo sc03Vo = null;
    	ObjectMapper mapper = new ObjectMapper();
    	SAXReader reader = new SAXReader(false);
    	InputSource source = null;
    	String str="";
		try {
			source = new InputSource(new ByteArrayInputStream(xmlStr.getBytes(encodeCharset)));
			source.setEncoding(encodeCharset);
	    	Document doc = reader.read(source);
	    	List<Element> els = doc.getRootElement().elements();
	    	for(Element el : els){
	    		if("payInfo".equals(el.getName())){
	    	            str = el.getTextTrim();
	    		}
	    	}
	    	
		}catch (DocumentException e) {
 			e.printStackTrace();
 		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			sc03Vo = mapper.readValue(str, SC03Vo.class);
		} catch (JsonParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	return sc03Vo;
    }
}